package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.user.UserFeignClient;
import com.heima.comment.dtos.CommentLikeDto;
import com.heima.comment.dtos.CommentListDto;
import com.heima.comment.dtos.CommentSaveDto;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.service.CommentService;
import com.heima.comment.vos.ApCommentVo;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constants.HotArticleConstants;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.UpdateArticleMess;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.ApThreadLocalUtil;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserFeignClient userFeignClient;

    //阿里云文本审核
    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;


    /**
     * 用户发表评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //校验参数
        if(dto.getArticleId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if(dto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE,"评论内容不能为空");
        }
        if(dto.getContent().length() > 140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论内容不能大于140字");
        }
        ApUser apUser = ApThreadLocalUtil.getUser();
        if(apUser == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        if(apUser.getId() == 0){
            return ResponseResult.okResult(401,"请先登录");
        }

        //查询用户信息
        //先从redis差,查不到再从user服务查
        String userJson = redisTemplate.opsForValue().get("LOGIN_USER_" + apUser.getId());
        if(userJson == null){
            //首次查询
            ResponseResult result = userFeignClient.findUserById(apUser.getId().longValue());
            if(result.getCode() == 200 && result.getData() != null){
                apUser = (ApUser) result.getData();
                //存到redis,并设置2小时的过期时间
                redisTemplate.opsForValue().set("LOGIN_USER_" + apUser.getId(), JSON.toJSONString(apUser),2L, TimeUnit.HOURS);
            }else{
                return ResponseResult.errorResult(result.getCode(),result.getErrorMessage());
            }
        }else{
            apUser = JSON.parseObject(userJson,ApUser.class);
        }

        //评论内容审核
        /*if(!scanTextFilter(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }*/

        //保存数据到mongodb中
        saveCommentToMongo(dto, apUser);

        //发送消息
        UpdateArticleMess mess=new UpdateArticleMess();
        mess.setAdd(1);
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        mess.setArticleId(dto.getArticleId());
        kafkaTemplate.send(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC, JSON.toJSONString(mess));

        return ResponseResult.okResult("评论成功");
    }


    /**
     * 保存数据到mongodb中
     * @param dto
     * @param apUser
     */
    private void saveCommentToMongo(CommentSaveDto dto, ApUser apUser) {
        ApComment apComment = new ApComment();
        apComment.setId(ObjectId.get().toHexString());
        apComment.setUserId(apUser.getId());
        apComment.setNickName(apUser.getName());
        apComment.setContent(dto.getContent());
        apComment.setTargetId(dto.getArticleId().toString());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(apUser.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        mongoTemplate.insert(apComment);
    }

    /**
     * 对评论信息进行安全审核
     * @param content
     */
    private Boolean scanTextFilter(String content) {
        Boolean flag = true;
        try {
            Map map = greenTextScan.greeTextScan(content);
            if (map != null && !map.get("suggestion").equals("pass")) {//表示违规
                flag = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    /**
     * 评论点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult likeComment(CommentLikeDto dto) {
        //1.检查参数
        if (dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.判断是否登录
        ApUser apUser = ApThreadLocalUtil.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.5 判断如果是游客身份则不允许发表评论
        if(apUser.getId()==0){
            return  ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"请登录之后再来点赞！！");
        }

        //判断当前评论信息是否存在，如果不存在，直接返回
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(apComment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //查询redis查看是否点赞过
        String comment_likes_key = "COMMENT_LIKES_" + apUser.getId();
        Boolean isLikes = redisTemplate.opsForSet().isMember(comment_likes_key, dto.getCommentId());
        //非法操作判断
        if((isLikes && dto.getOperation() == 0) || (!isLikes && dto.getOperation() == 1)){
            return ResponseResult.okResult(500,"非法操作");
        }
        //正常点赞操作,新增redis,新增mongo中的点赞集合，修改mongo中的评论集合，点赞数+1
        if(!isLikes && dto.getOperation() == 0){
            //新增redis
            redisTemplate.opsForSet().add(comment_likes_key,dto.getCommentId());
            //新增mongodb
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setId(ObjectId.get().toHexString());
            apCommentLike.setTargetId(dto.getCommentId());
            apCommentLike.setCreatedTime(new Date());
            apCommentLike.setUserId(apUser.getId());
            mongoTemplate.insert(apCommentLike);
            //修改comment
            Query query = Query.query(Criteria.where("id").is(apComment.getId()));
            Update update = new Update().inc("likes", 1);
            mongoTemplate.updateFirst(query,update,ApComment.class);
        }
        //正常取消点赞操作
        if(isLikes && dto.getOperation() == 1){
            //删除redis
            redisTemplate.opsForSet().remove(comment_likes_key,dto.getCommentId());
            //删除mongodb
            mongoTemplate.remove(Query.query(Criteria.where("userId").is(apUser.getId())
                    .and("targetId").is(dto.getCommentId())),ApCommentLike.class);
            //修改comment
            Query query = Query.query(Criteria.where("id").is(apComment.getId()).and("likes").gt(0));
            Update update = new Update().inc("likes", -1);
            mongoTemplate.updateFirst(query,update,ApComment.class);
        }
        //返回数据
        mongoTemplate.findById(dto.getCommentId(),ApComment.class);
        Map map = new HashMap();
        map.put("likes",apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    @Override
    public ResponseResult findByArticleId(CommentListDto dto) {
        //校验参数
        if(dto.getArticleId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getSize() == null || dto.getSize() <= 0){
            dto.setSize(10);
        }
        //最大显示50条
        dto.setSize(Math.min(50,dto.getSize()));
        //根据文章id查询mongodb评论,分页降序排序
        Query query = Query.query(Criteria.where("targetId").is(dto.getArticleId().toString())
                        .and("createdTime").lt(dto.getMinDate())).with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(dto.getSize());
        List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);
        if(commentList == null || commentList.size() < 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //如果是游客登录,直接返回评论列表,无需判断点赞情况
        ApUser apUser = ApThreadLocalUtil.getUser();
        if(apUser.getId() == 0){
            return ResponseResult.okResult(commentList);
        }
        //如果是用户登录,就要判断点赞状态
        //查询redis点赞数据
        String key = "COMMENT_LIKES_" + apUser.getId();
        Set<String> like_ids = redisTemplate.opsForSet().members(key);
        if(like_ids == null){
            //不作处理,直接返回评论列表
            return ResponseResult.okResult(commentList);
        }
        //存在点赞数据,要返回标记
        List<ApCommentVo> list = commentList.stream().map(comment -> {
            ApCommentVo vo = new ApCommentVo();
            BeanUtils.copyProperties(comment, vo);
            if (like_ids.contains(comment.getId())) {
                vo.setOperation((short) 0);
            }
            return vo;
        }).collect(Collectors.toList());
        return ResponseResult.okResult(list);
    }
}
